#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version        : 1.0
# @Creaet Time    : 2021/10/18 22:19 
# @File           : main.py
# @IDE            : PyCharm
# @desc           : 接口


from typing import List

from fastapi import Depends, APIRouter, HTTPException
from sqlalchemy.orm import Session

from . import crud, schemas
from .database import SessionLocal, engine, Model

"""创建数据库表"""
Model.metadata.create_all(bind=engine)

app = APIRouter()


"""数据库依赖项，它将在单个请求中使用，然后在请求完成后将其关闭。"""
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


"""
提示：
参数 db 实际上是 SessionLocal 类型，但是此类（使用 sessionmaker() 创建）是SQLAlchemy Session 的『代理』，因此，编辑器并不真正知道哪种方法是提供。
但通过将类型声明为 Session，编辑器现在可以知道可用的方法（.add()、.query()、.commit()等），并且可以提供更好的支持（例如自动补全）。类型声明不影响实际对象。

提示：
还请注意，有一些具有标准 Python 类型的 response_models，如 List[schemas.User]。
但是，由于该 List 的内容 / 参数是带有 orm_mode 的 Pydantic 模型，因此将正常检索数据并将其返回给客户端，而不会出现问题。

关于 def 与 async def：
在这里，我们在路径操作函数内部和依赖项中使用 SQLAlchemy 代码，然后它将与外部数据库进行通信。
这可能需要一些『等待』。
但是由于 SQLAlchemy 不具有await直接使用的兼容性，就像使用以下内容一样：
user = await db.query(User).first()
而我们正在使用：
user = db.query(User).first()
所以：我们应该声明路径操作函数和不带 async def 的依赖项，而仅使用普通的 def
"""


@app.post("/users/", response_model=schemas.User, summary="创建用户")
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
    db_user = crud.get_user_by_email(db, email=user.email)
    if db_user:
        raise HTTPException(status_code=400, detail="邮箱已经存在")
    return crud.create_user(db=db, user=user)


@app.get("/users/", response_model=List[schemas.User], summary="获取用户列表")
def get_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    users = crud.get_users(db, skip=skip, limit=limit)
    return users


@app.get("/users/{user_id}", response_model=schemas.User, summary="获取单个用户")
def get_user(user_id: int, db: Session = Depends(get_db)):
    db_user = crud.get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(status_code=404, detail="用户不存在")
    print(db_user)
    return db_user


@app.post("/users/{user_id}/items/", response_model=schemas.Item, summary="创建项目")
def create_item_for_user(user_id: int, item: schemas.ItemCreate, db: Session = Depends(get_db)):
    return crud.create_user_item(db=db, item=item, user_id=user_id)


@app.get("/items/", response_model=List[schemas.Item], summary="获取项目列表")
def read_items(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    items = crud.get_items(db, skip=skip, limit=limit)
    return items